package com.magina.machine.config;

import com.magina.machine.listener.ApproveStateListener;
import com.magina.machine.model.ApproveEvent;
import com.magina.machine.model.ApproveStatus;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.statemachine.config.EnableStateMachineFactory;
import org.springframework.statemachine.config.EnumStateMachineConfigurerAdapter;
import org.springframework.statemachine.config.StateMachineFactory;
import org.springframework.statemachine.config.builders.StateMachineConfigurationConfigurer;
import org.springframework.statemachine.config.builders.StateMachineStateConfigurer;
import org.springframework.statemachine.config.builders.StateMachineTransitionConfigurer;
import org.springframework.statemachine.persist.StateMachineRuntimePersister;
import org.springframework.statemachine.service.DefaultStateMachineService;
import org.springframework.statemachine.service.StateMachineService;

import java.util.EnumSet;

@Configuration
@EnableStateMachineFactory(name="approveMachineFactory")
public class ApprovalMachineConfig extends EnumStateMachineConfigurerAdapter<ApproveStatus, ApproveEvent> {

    @Autowired
    @Qualifier("approveStateListener")
    private ApproveStateListener approveStateListener;
    @Autowired
    @Qualifier("approveRedisPersister")
    private StateMachineRuntimePersister<ApproveStatus, ApproveEvent, String> approveRedisPersister;

    @Override
    public void configure(StateMachineConfigurationConfigurer<ApproveStatus, ApproveEvent> config)
            throws Exception {
        config
                .withConfiguration()
                .autoStartup(false)
                .listener(approveStateListener)

                .and()
                .withPersistence()
                .runtimePersister(approveRedisPersister);
    }

    @Override
    public void configure(StateMachineStateConfigurer<ApproveStatus, ApproveEvent> states)
            throws Exception {
        states
                .withStates()
                .initial(ApproveStatus.DRAFT)
                .states(EnumSet.allOf(ApproveStatus.class));

    }

    @Override
    public void configure(StateMachineTransitionConfigurer<ApproveStatus, ApproveEvent> transitions)
            throws Exception {
        transitions
                .withExternal().source(ApproveStatus.DRAFT).target(ApproveStatus.NON_APPROVAL)
                .event(ApproveEvent.LAUNCH)
                .and()
                .withExternal().source(ApproveStatus.NON_APPROVAL).target(ApproveStatus.ON_APPROVAL)
                .event(ApproveEvent.APPROVE)
                .and()
                .withExternal().source(ApproveStatus.ON_APPROVAL).target(ApproveStatus.COMPLETE_APPROVAL)
                .event(ApproveEvent.COMPLETE)
                .and()
                .withExternal().source(ApproveStatus.ON_APPROVAL).target(ApproveStatus.REFUSE_APPROVAL)
                .event(ApproveEvent.REFUSE);

    }

    @Bean(name = "approveMachineService")
    public StateMachineService<ApproveStatus, ApproveEvent> stateMachineService(@Qualifier("approveMachineFactory") StateMachineFactory<ApproveStatus, ApproveEvent> stateMachineFactory,
                                                                                @Qualifier("approveRedisPersister") StateMachineRuntimePersister<ApproveStatus, ApproveEvent, String> stateMachineRuntimePersister) {
        return new DefaultStateMachineService<ApproveStatus, ApproveEvent>(stateMachineFactory, stateMachineRuntimePersister);
    }
}